﻿using BZ.Core.TaskExt;
using BZ.Logger;
using BZVision;
using NDK.Frm;
using NDK.Module.DAL;
using NDK.Module.StationLogic;
using NDK.Motion.BLL;
using NDK.Motion.MachineManager;
using NDK.Utils;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using VisionPlatform;
using static NDK.Module.BLL.Configuration;
using static NDK.Module.Model.Common;

namespace NDK.Module.BLL
{
    public static class SysInit
    {
        /// <summary>
        /// 初始化框架，一般在程序启动时调用一次
        /// </summary>
        /// <param name="showStartWindow">指示是否显示程序启动时的欢迎窗体</param>
        public static void Init()
        {
            try
            {
                //加载中英文切换字典，可写到配置文件，这里写死了
                languageDic.Add("Function", "功能");
                languageDic.Add("StartVelocity", "初速度");
                languageDic.Add("MoveVelocity", "运行速度");
                languageDic.Add("AccTime", "加速时间");
                languageDic.Add("DecTime", "减速时间");
                languageDic.Add("AxisPriority", "优先级");
                languageDic.Add("Project", "项目");
                languageDic.Add("Description", "说明");

                Dlg_SelectProject selectProjectDialog = new Dlg_SelectProject();
                if (selectProjectDialog.ShowDialog(Frm_Home.Instance) == DialogResult.OK)
                {
                    MachineDataManager.LoadFromFile();
                    PublicMethod.LoadProTypeMeasureItemEnableConfig();
                    PublicMethod.LoadProTypeParam();
                    Frm_Welcome.Instance.Show();
                    Application.DoEvents();
                    Frm_InitItemStatu.Instance.UpdateStep(1, language == Language.English ? "Loading Forms..." : "正在加载窗体...", true);
                    Frm_Main frm = null;
                    try
                    {
                        frm = Frm_Main.Instance;          //这一句看似没用，实则有用，因为在这里加这一行就会实例化主窗体，不然主窗体就会在后台线程中被实例化，那就会有问题
                        var frm_setting = Frm_Setting.Instance;
                        var alarmFrom = Frm_Alarm2.Instance;

                        var frm_Login = Frm_Login.Instance;
                        var frm_Statistics = Frm_Statistics.Instance;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"未处理的异常：{ex.StackTrace}");
                    }
                    Frm_InitItemStatu.Instance.UpdateStep(2, language == Language.English ? "Forms Load OK" : "窗体加载成功！", true);
                    Application.DoEvents();
                    TaskManager.Run(() =>
                    {
                        MachineInit();
                    });
                    while (loading == true)
                    {
                        Thread.Sleep(5);
                        Application.DoEvents();
                    }

                    Frm_Welcome.Instance.Close();
                    frm.ShowDialog();
                }
            }
            catch (Exception ex)
            {
                try
                {
                    Frm_Welcome.Instance.ShowDialog();
                }
                catch (System.Exception es)
                {
                    if (ex.Message.Contains("DevComponents.DotNetBar2"))
                    {
                        DialogResult result = MessageBox.Show(language == Language.English ? "An image with the same name already exists, is it overwritten?" : "启动失败，本机未安装此程序所依赖的组件，是否立即安装？", language == Language.English ? "Tip:" : "提示：", MessageBoxButtons.YesNo);
                        if (result == DialogResult.Yes)
                        {
                            Process.Start(Application.StartupPath + "\\Installs\\DotNetBar for Windows Forms 12.0.0.1.exe");
                        }
                    }
                    else
                    {
                    }
                }
            }
        }
        /// <summary>
        /// 表示程序启动时是否初始化成功
        /// </summary>
        internal static bool initSucceed = true;
        /// <summary>
        /// 是否处于前台生产状态，分前台生产状态和后台调试状态
        /// </summary>
        internal static bool productionMode = true;
        /// <summary>
        /// 记录旧的时间
        /// </summary>
        internal static DateTime oldTime = DateTime.Now;
        /// <summary>
        /// 总生产时间
        /// </summary>
        internal static TimeSpan runTime;
        /// <summary>
        /// 总待机时间
        /// </summary>
        internal static TimeSpan waitTime;
        /// <summary>
        /// 总报警时间
        /// </summary>
        internal static TimeSpan alarmTime;
        /// <summary>
        /// 资源锁
        /// </summary>
        internal static object lock_resources = new object();
        /// <summary>
        /// 是否已经显示
        /// </summary>
        internal static bool hasShown = false;
        internal static bool loading = true;
        internal static bool iSMachineInit = true;


        /// <summary>
        /// 初始化
        /// </summary>
        //[Interceptor]
        public static void MachineInit()
        {
            try
            {
                #region 读取软件版本
                try
                {
                    string path = Application.StartupPath + @"\Config\SoftwareVersionInfo.csv";

                    DataTable dt = FileUtils.OpenCSV(path);
                    string LocalVersion = dt.Rows[dt.Rows.Count - 1][0].ToString();
                    if (currentVersion != LocalVersion)
                    {
                        AppendUiLog.Log("本地配置文件版本与软件版本不一致");
                    }
                    else
                    {
                        Frm_Main.Instance.Text += LocalVersion;
                    }


                    Frm_InitItemStatu.Instance.UpdateStep(3, language == Language.English ? "Open SoftWare Version Info" : "读取软件版本信息", true);
                }
                catch (Exception)
                {
                    Frm_InitItemStatu.Instance.UpdateStep(3, language == Language.English ? "Open SoftWare Version Info" : "读取软件版本信息", false);
                    iSMachineInit = false;
                }
                #endregion

                #region 读取配置文件
                try
                {
                    Read();
                    Frm_InitItemStatu.Instance.UpdateStep(5, language == Language.English ? "Reading Configer File" : "读取配置文件1", true);
                }
                catch (Exception)
                {
                    Frm_InitItemStatu.Instance.UpdateStep(5, language == Language.English ? "Reading Configer File" : "读取配置文件1", false);
                    iSMachineInit = false;
                }
                #endregion

                #region 更新系统参数
                try
                {
                    PublicMethod.UpdateRuningData();   //还是需要挑选哪些变量要更新

                    AlarmInfoServices alarmInfoServices = new AlarmInfoServices();
                    DateTime dt = DateTime.Now.AddDays(-SaveDaysOfAlarmInfo);//删除N天前的报警信息
                    alarmInfoServices.DeleteBeforeTime(dt);
                    if (Line == "左")
                    {
                        string[] fileNames_book = FileUtils.GetFileNames(SafeFilePath);
                        foreach (string fileName in fileNames_book)
                        {
                            string temp = fileName.ToLower();//统一转换为小写
                            if (temp.Contains("safteydoor.csv"))
                            {
                                List<string> strings = FileUtils.OpenCSV1(temp);
                                foreach (string s in strings)
                                {
                                    ListSafteyDoor.Add(new GetCSVParam()
                                    {
                                        Name = s.Split(',')[0],
                                        Number = Convert.ToInt32(s.Split(',')[1])
                                    });
                                }
                            }
                            if (temp.Contains("safteylight.csv"))
                            {
                                List<string> strings = FileUtils.OpenCSV1(temp);
                                foreach (string s in strings)
                                {
                                    ListSafteyLight.Add(new GetCSVParam()
                                    {
                                        Name = s.Split(',')[0],
                                        Number = Convert.ToInt32(s.Split(',')[1])
                                    });
                                }
                            }
                        }
                    }

                    Frm_InitItemStatu.Instance.UpdateStep(10, "更新系统参数成功", true);
                }
                catch (Exception ex)
                {
                    Frm_InitItemStatu.Instance.UpdateStep(10, "更新系统参数失败", false);
                    iSMachineInit = false;
                }
                #endregion

#if false
                #region 指纹仪初始化
                try
                {
                    if (Frm_Login.Instance.InitFPDevice())
                    {
                        isFingerPrintInitialed = true;
                        Frm_InitItemStatu.Instance.UpdateStep(10, language == Language.English ? "Initial FingerPrint Device Success" : "初始化指纹仪成功", true);
                    }
                    else
                    {
                        isFingerPrintInitialed = false;
                        Frm_InitItemStatu.Instance.UpdateStep(10, language == Language.English ? "Initial FingerPrint Device Fail" : "初始化指纹仪失败", false);
                    }
                }
                catch (Exception)
                {
                    isFingerPrintInitialed = false;
                    Frm_InitItemStatu.Instance.UpdateStep(10, language == Language.English ? "Initial FingerPrint Device Fail" : "初始化指纹仪异常", false);
                }
                #endregion
#endif
                if (!isLoadOffLine)
                {
                    #region 连接MES上传系统
                    if (Line == "右")
                        StationTCP.IniMesSever();
                    #endregion

                    #region 初始化相机
                    PublicMethod.UpdateRuningData();
                    Frm_InitItemStatu.Instance.UpdateStep(65, "初始化MindVision相机", true);
                    if (!PublicMethod.MindVision())
                    {
                        iSMachineInit = false;
                        Frm_InitItemStatu.Instance.UpdateStep(70, "初始化相机失败", false);
                        AppendUiLog.Log("相机加载失败 ", LogType.Error);
                    }
                    else
                    {
                        Frm_InitItemStatu.Instance.UpdateStep(70, "初始化相机成功", true);
                        AppendUiLog.Log("相机加载成功 ", LogType.Info);
                    }
                    #endregion

                    #region 光源初始化
                    try
                    {
                        Frm_InitItemStatu.Instance.UpdateStep(22, "初始化光源控制器", true);
                        foreach (var lightController in MachineDataManager.Instance.LightControllerList)
                        {
                            lightController.Disconnect();
                            if (lightController.IsConnect == false)
                            {
                                if (lightController.Connect())
                                {
                                    lightController.CloseAllLight();
                                }
                                else
                                {
                                    iSMachineInit = false;
                                    Frm_InitItemStatu.Instance.UpdateStep(25, "初始化光源控制器失败", false);
                                    AppendUiLog.Log("初始化光源控制器失败", LogType.Error);
                                }
                            }
                            else
                            {

                            }
                        }
                        if (iSMachineInit)
                        {
                            Frm_InitItemStatu.Instance.UpdateStep(25, "初始化光源控制器成功", true);
                            AppendUiLog.Log("初始化光源控制器成功", LogType.Info);
                        }
                    }
                    catch (Exception ex)
                    {
                        //Common.isLightControlInitialed = false;
                        Frm_InitItemStatu.Instance.UpdateStep(25, "初始化光源控制器异常", false);
                        AppendUiLog.Log("初始化光源控制器异常", LogType.Error);
                        iSMachineInit = false;
                    }
                    #endregion

                    #region PPG初始化
                    try
                    {
                        if (Line == "右")
                        {
                            Frm_InitItemStatu.Instance.UpdateStep(33, "初始化PPG", true);
                            if (Machine.PPG.Init(PPGIP, 64000))
                            {
                                Frm_InitItemStatu.Instance.UpdateStep(35, "初始化PPG成功", true);
                                AppendUiLog.Log("初始化PPG成功", LogType.Info);
                            }
                            else
                            {
                                Frm_InitItemStatu.Instance.UpdateStep(35, "初始化PPG失败", false);
                                AppendUiLog.Log("初始化PPG失败", LogType.Error);
                                iSMachineInit = false;
                            }
                        }

                    }
                    catch (Exception ex)
                    {
                        Frm_InitItemStatu.Instance.UpdateStep(35, "初始化PPG异常", false);
                        AppendUiLog.Log("初始化PPG异常", LogType.Error);
                        iSMachineInit = false;
                    }
                    #endregion

                    #region 加载视觉框架
                    try
                    {
                        Vision.Intial();
                        ////////    我们不要他,它，她
                        ////////    VisionManager.Event.LogDebug += Event_LogDebug;
                        ////////    VisionManager.Event.LogError += Event_LogError;
                        ////////    VisionManager.Event.LogFatal += Event_LogFatal;
                        ////////    VisionManager.Event.LogInfo += Event_LogInfo;
                        ////////    VisionManager.Event.LogWarn += Event_LogWarn;
                        ////////    VisionManager.Event.LogModify += Event_LogModify;

                        if (PublicMethod.LoadSlp(SLP_Path))
                        {
                            Frm_InitItemStatu.Instance.UpdateStep(71, "加载算法Slp路径成功", true);
                        }

                        else
                        {
                            Frm_InitItemStatu.Instance.UpdateStep(70, "加载算法Slp路径失败", false);
                            MessageBox.Show($"{SLP_Path}:算法加载失败");
                        }

                    }
                    catch (Exception ex)
                    {

                    }
                    #region 初始化视觉框架变量
                    VisionManager.Engine eng = null;
                    eng = new VisionManager.Engine("InitialVariable");
                    eng.ActionFun();
                    #endregion
                    #endregion

                    #region[设置线程池]
                    ThreadPool.GetMaxThreads(out var works, out var threads);
                    if (ThreadPool.SetMaxThreads(1000, 24))
                    {
                        if (ThreadPool.SetMaxThreads(100, 24))
                        {
                            AppendUiLog.Log("线程池设置成功", LogType.Info);
                        }
                    }
                    ThreadPool.GetAvailableThreads(out works, out threads);
                    #endregion
                }
                #region 连接上下料机PLC/与ATL的PLC连接

                Machine.OmronPLC_Up.Connect(PLC_IP);
                Machine.OmronPLC_Down.Connect(PLC_IP);
                Machine.OmronPLC_Hearb.Connect(PLC_IP);
                if (!Machine.OmronPLC_Up.ConnectStatus && !Machine.OmronPLC_Up.ConnectStatus && !Machine.OmronPLC_Down.ConnectStatus && !Machine.OmronPLC_Down.ConnectStatus && !Machine.OmronPLC_Hearb.ConnectStatus)
                {
                    iSMachineInit = false;
                    Frm_InitItemStatu.Instance.UpdateStep(15, language == Language.English ? "" : "连接PLC失败", false);
                }
                else
                {
                    Frm_InitItemStatu.Instance.UpdateStep(15, language == Language.English ? "" : "初始化PLC成功", true);
                    AppendUiLog.Log("初始化PLC成功", LogType.Info);
                }
                PublicMethod.ShowText(Frm_Main.Instance.lbPLCStatus, Machine.OmronPLC_Hearb.ConnectStatus == true ? "上料PLC连接成功" : "上料PLC连接失败", Machine.OmronPLC_Hearb.ConnectStatus == true ? Color.Green : Color.Red, Color.Black);


                //Machine.omronPLCFins.Connect(ATL_PLC_IP, Convert.ToInt32(ATL_PLC_Port));//连接ATL虚拟PLC
                //if (!Machine.omronPLCFins.ConnectStatus)
                //{
                //    Frm_InitItemStatu.Instance.UpdateStep(15, language == Language.English ? "" : "连接ATL虚拟PLC失败", false);
                //}
                //else
                //{
                //    Frm_InitItemStatu.Instance.UpdateStep(15, language == Language.English ? "" : "初始化ATL虚拟PLC成功", true);
                //    AppendUiLog.Log("初始化ATL虚拟PLC成功", LogType.Info);
                //}
                #endregion

                StationTCP.StationTCPInit();
                #region 运动板卡初始化
                try
                {
                    //MachineDataManager.LoadFromFile();
                    if (MachineDataManager.Instance.CardList.Count > 0)
                    {

                        //如果在界面手动初始化了，这里就不需要再初始化了
                        foreach (var card in MachineDataManager.Instance.CardList)
                        {
                            //运动卡初始化

                            try
                            {
                                bool isSuccess = card.CardInit(0);
                                if (isSuccess == false)
                                {
                                    AppendUiLog.Log("运动卡初始化失败！", LogType.Error);
                                    Frm_InitItemStatu.Instance.UpdateStep(90, "运动卡初始化失败!", false);
                                    loading = false;
                                    iSMachineInit = false;
                                    return;
                                }
                            }
                            catch (Exception ex)
                            {
                                AppendUiLog.Log("板卡初始化发生异常！", LogType.Error);
                                Frm_InitItemStatu.Instance.UpdateStep(90, "板卡初始化发生异常!", false);
                                loading = false;
                                iSMachineInit = false;
                                return;
                            }
                            card.Initialized = true;
                        }
                        Frm_InitItemStatu.Instance.UpdateStep(93, "运动卡初始化成功", true);
                        AppendUiLog.Log("运动卡初始化成功", LogType.Info);

                        Machine.MachineResourceInit();
                        MotionControl.PropertyChanged += MotionControl_PropertyChanged;

                        //报警清除
                        foreach (var axis in MachineDataManager.Instance.AxisList)
                        {

                            bool ret = axis.ClearAlarm();
                            if (ret == false)
                            {
                                Frm_InitItemStatu.Instance.UpdateStep(95, $"运动板卡清除轴[{axis.AxisID}]报警失败", false);
                                AppendUiLog.Log($"运动板卡清除轴[{axis.AxisID}]报警失败", LogType.Error);
                                iSMachineInit = false;
                            }
                        }
                        Frm_InitItemStatu.Instance.UpdateStep(95, "运动板卡清除报警成功！", true);

                        MotionControl.RES res = MotionControl.AllAxisServoON();
                        if (res.bRtn == true)
                        {
                            isCardInitialed = true;
                            Frm_InitItemStatu.Instance.UpdateStep(95, "初始化运动板卡参数成功", true);
                            AppendUiLog.Log("初始化运动板卡参数成功", LogType.Info);
                        }
                        else
                        {
                            isCardInitialed = false;
                            Frm_InitItemStatu.Instance.UpdateStep(95, "运动板卡上使能失败", false);
                            AppendUiLog.Log("运动板卡上使能失败", LogType.Error);
                            iSMachineInit = false;
                        }
                    }
                    if (ConsumerAdress == "NVT" && ProjectName.Contains("4062"))
                    {
                        if (!MotionControl.IniMiniEcatLib(Environment.CurrentDirectory + @"\Config\E4O4配置文件.ini", 1))
                        {
                            iSMachineInit = false;
                            Frm_InitItemStatu.Instance.UpdateStep(80, $"飞拍Mini连接失败", false);
                            AppendUiLog.Log($"飞拍Mini连接失败", LogType.Error);
                        }
                    }

                }
                catch (Exception ex)
                {
                    isCardInitialed = false;
                    iSMachineInit = false;
                    AppendUiLog.Log("运动板卡" + Machine.AdlinkCard.CardID + "初始化失败...", LogType.Alert);
                    Frm_InitItemStatu.Instance.UpdateStep(95, "初始化运动板卡参数异常", false);
                }
                #endregion

                #region 最终判定
                if (/*Common.isVisionModularInitialed &&*/ iSMachineInit /*&& Common.isConnectAppleInitialed*/                                                                      /* && Common.isLightControlInitialed*/)//Common.isFingerPrintInitialed
                {
                    b硬件初始化成功 = true;
                    Frm_InitItemStatu.Instance.UpdateStep(100, "设备硬件初始化成功，准备复位", true);
                }
                else
                {
                    b硬件初始化成功 = false;
                    Frm_InitItemStatu.Instance.UpdateStep(100, "设备硬件初始化失败，请检查", false);
                }

                loading = false;
                #endregion

            }
            catch (Exception ex)
            {
                loading = false;
                Frm_InitItemStatu.Instance.UpdateStep(100, "设备初始化失败，请检查", false);
            }
        }

        private static void MotionControl_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            AppendUiLog.Log(e.PropertyName, LogType.Alert);
        }


        // Any attribute which provides OnEntry/OnExit/OnException with proper args
        [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Assembly | AttributeTargets.Module)]
        public class InterceptorAttribute : Attribute
        {
            // instance, method and args can be captured here and stored in attribute instance fields
            // for future usage in OnEntry/OnExit/OnException
            public void Init(object instance, MethodBase method, object[] args)
            {
                Console.WriteLine(string.Format("Init: {0} [{1}]", method.DeclaringType.FullName + "." + method.Name, args.Length));
            }

            public void OnEntry()
            {
                Console.WriteLine("OnEntry");
            }

            public void OnExit()
            {
                Console.WriteLine("OnExit");
            }

            public void OnException(Exception exception)
            {
                MessageBox.Show(string.Format("OnException: {0}: {1}", exception.GetType(), exception.Message));
            }
        }

    }
}
